package ac.il.technion.cs236635.project.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;

import org.apache.log4j.Logger;

@WebService
public class Dispatcher {

	private Map<String, ServerInfo> registered = new HashMap< String, ServerInfo>( );
	
	private List<String> servers = new ArrayList<String>( );
	
	private Object locker = new Object( );

	private static final Logger logger = Logger.getLogger( Dispatcher.class);
	
	/**
	 * @param info - registration information about the server
	 * @return status of registration operation, returns <b>true</b>
	 * whenever operation has succeeded or <b>false</b> otherwise
	 */
	@WebMethod( operationName = "register")
	public boolean registerServer( ServerInfo info) {
		
		synchronized( locker) {
			if ( servers.contains( info.getServerName( )))
				return false;
			registered.put( info.getServerName(), info);
			servers.add( info.getServerName( ));
			logger.info( new StringBuilder( ).append( "New server has registered. ")
						.append( "Server name: ").append( info.getServerName( ))
						.append( ",").append( " server address: ")
						.append( info.getServerEnpoint( )));
		}
		
		return true;
	}
	
	/**
	 * @return - returns connection of information of
	 * randomly picked server from the registered list.
	 */
	@WebMethod( operationName = "acquire")
	public ServerPair acquireServer( ) {
		Random random = new Random( );
		
		if (registered.size() < 2)
			return null;

		synchronized( locker) {
			int hpIndex = random.nextInt( registered.size( ));
			int lpIndex;

			while ((lpIndex = random.nextInt( registered.size( ))) == hpIndex);

			return new ServerPair(registered.get( servers.get(hpIndex)),
				registered.get(servers.get(lpIndex)));
		}
	}
	
	
	public static void main(String[] args) {
		Endpoint endpoint = Endpoint.create( new Dispatcher( ));
		endpoint.publish( "http://localhost:8080/Dispatcher");

		try {
			logger.info( "Dispatcher has started to listen");
			while (true) {
				Thread.sleep(100);
			}
		} catch( Exception e) {
			e.printStackTrace( );
		} finally {
			endpoint.stop( );
		}
	}
}